package de.koller.aframe.util.web.basicHTML;

import de.koller.aframe.util.node.NodeA;
import de.koller.aframe.util.thread.ILoopHandler;
import de.koller.aframe.util.thread.ThreadRootHandle;
import de.koller.oceanFramework.OceanException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

public class BasicWebServer extends NodeA {
	
	private final int port;
	private final ThreadRootHandle thread;
	private ServerSocket server;
	
	private final Map<String, IPage> pages = new HashMap<>();
	private final ErrorPage errorpage = new ErrorPage( this );
	
	public BasicWebServer( int port ) {
		this.port = port;
		thread = new ThreadRootHandle( "web:" + port );
	}
	
	public void addPage( String requestStart, IPage page ) {
		this.pages.put( requestStart, page );
	}
	
	@Override
	protected void init() {
		super.init();
		
		try {
			setupServer();
		} catch( IOException ex ) { 
			throw new OceanException( ex );
		}
		
		thread.getThread().setDaemon( true );
		thread.setLoopHandler( new BasicWebServer.RequestHandle() );
		thread.start();
		
		System.out.println( "Server startet on localhost and port " + port );
	}

	private void setupServer() throws IOException {
		server = new ServerSocket( port );
	}
	
	@Override
	protected void release() {
		super.release();
		
		thread.stop();
	}
	
	public void responde( String request, OutputStream out ) {
		try {
			IPage found = null;
			int founds = 0;
			
			for( String r : pages.keySet() )
				if( request.startsWith( r ) ) {
					IPage p = pages.get( r );
					if( !p.isRequestValid( request ) )
						continue;
					found = p;
					founds++;
				}
			
			if( found == null ) {
				errorpage.setMessage( "Request nicht gefunden", 
						"Der angeforderte Link wurde diesem Webserver nicht zugeteilt." );
				errorpage.print( out, request );
			} else if( founds > 1 ) {
				errorpage.setMessage( "Request nicht eindeutig", 
						"Der angeforderte Request konnte nicht eindeutig aufgelöst werden." );
				errorpage.print( out, request );
			} else
				found.print( out, request );
				
			out.flush();
		} catch ( IOException ex ) {
			System.err.println( ex );
		}
	}
	
	private class RequestHandle implements ILoopHandler {

		@Override
		public void loopHandle() {
			try {
				handle();
			} catch( IOException ex ) {
				System.err.println( ex );
			}
		}
		
		private void handle() throws IOException {
			Socket s = server.accept();
			BufferedReader in = new BufferedReader( new InputStreamReader( s.getInputStream() ) );
			String str = in.readLine();
			while( str != null && !str.isEmpty() ) {
				if( str.startsWith( "GET" ) )
					break;
				str = in.readLine();
			}
			
			if( str == null || !str.startsWith( "GET" ) ) {
				s.close();
				return;
			}
			
			StringTokenizer st = new StringTokenizer( str );
			st.nextToken();
			
			responde( st.nextToken(), s.getOutputStream() );
			s.close();
		}
		
	}	
}
